import { sendBackgroundMessage, sendContentMessage, addOnMessageListener } from "./chrome"
import logger from "./logger"

/** 消息类型 */
export enum MessageType {
    /** content 启动 */
    CONTENT_START = 'content start',
    /** content 关闭 */
    CONTENT_STOP = 'content stop',

    /** content 发起 通过 background 代理发送请求 */
    FETCH = 'fetch',

    /** content 发起 通过 background 代理发送请求 */
    SSE = 'sse',

    /** 打开 页面 */
    OPEN_PAGE = 'open page',

    /** content页面刷新 */
    RELOAD = 'reload',
}

export enum MessageTypeSub {
    SSE_OPEN ='sse open',
    SSE_MESSAGE = 'sse message',
    SSE_CLOSE = 'sse close',
    SSE_ERROR = 'sse error',
}

/** 系统中使用的统一消息格式 */
export interface MessageInfo<T = unknown, F extends MessageType = MessageType> {
    /** 消息类型 */
    type: F,
    subType?: MessageTypeSub,
    uuid?: string,
    from?: RunScope,
    /** 消息内容 */
    data?: T,
}

/**
 * 消息发送通用方法
 * @param msg 消息体
 * @returns 响应返回
 */
export const sendMessage = async function <T, F = boolean>(msg: MessageInfo<T> | MessageType, data?: T) {
    let message: MessageInfo<T>
    if (typeof msg === 'string') {
        message = { type: msg, data }
    } else {
        message = msg
    }
    message.from = __SCOPE__
    switch (__SCOPE__) {
        case RunScope.Content:
        case RunScope.Main:
            logger.debug(new Date().toLocaleTimeString(), __SCOPE__, 'send:', message)
            return sendBackgroundMessage<MessageInfo<T>, F>(message)
        case RunScope.Background:
        case RunScope.Popup:
            logger.debug(new Date().toLocaleTimeString(), __SCOPE__, 'send:', message)
            return sendContentMessage<MessageInfo<T>, F extends Array<infer N> ? N : never>(message)
    }
}

export interface MessageListener<T, F extends MessageType = MessageType> {
    (message: MessageInfo<T, F>, sender?: chrome.runtime.MessageSender): void | boolean
}
/** 消息监听通用方法 */
const _addMessageListener = function <T>(listener: MessageListener<T>) {
    addOnMessageListener<MessageInfo<T>, boolean>(function (msg, sender, sendResponse) {
        const res = listener(msg, sender)
        sendResponse()
        return typeof res != 'undefined' ? res : true
    })
}

type AddMessageListenerType<T, F extends MessageType = MessageType> = {
    (listener: MessageListener<T, F>): void,
} | {
    (type: F | F[], listener: MessageListener<T, F>): void,
} | {
    (listeners: Record<F, MessageListener<T, F>>): void,
}

/** 消息监听方法多参数封装 */
export const addMessageListener = <T>(...args: Parameters<AddMessageListenerType<T>>) => {
    const [temp, listener] = args
    if (typeof temp === 'function') {
        _addMessageListener<T>(temp)
        return
    }
    if (Array.isArray(temp)) {
        _addMessageListener<T>(function (msg, sender) {
            for (const type of temp) {
                if (msg.type === type) {
                    listener(msg, sender)
                }
            }
        })
    } else if (typeof temp === 'string') {
        _addMessageListener<T>(function (msg, sender) {
            if (msg.type === temp) {
                listener(msg, sender)
            }
        })
    } else {
        _addMessageListener<T>(function (msg, sender) {
            temp[msg.type]?.(msg, sender)
        })
    }
}
